package store

import (
	"editor/constant"
	"fmt"
	"github.com/gin-gonic/gin"
	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
	"github.com/rifflock/lfshook"
	"github.com/sirupsen/logrus"
	"io"
	"net/http"
	"os"
	"path"
	"sync"
	"time"
)

var (
	logOnce sync.Once
	Logger  *logrus.Logger
)

func logInit(ctx *gin.Context) (err error) {
	logOnce.Do(func() {
		c := constant.Config.Log
		logFilePath := c.Dir
		logFileName := c.Name
		if logFilePath == "" {
			logFilePath = "./logs/"
		}
		err = os.MkdirAll(logFilePath, 0666)
		if err != nil {
			err = fmt.Errorf("create log dir failed ,error : %v", err)
			return
		}

		if logFileName == "" {
			logFileName = "app.log"
		}
		fileName := path.Join(logFilePath, logFileName)

		//写入文件
		var logFile *os.File
		logFile, err = os.OpenFile(fileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
		if err != nil {
			return
		}

		// 实例化
		Logger = logrus.New()
		// 设置输出
		Logger.Out = io.MultiWriter(logFile, os.Stdout)

		// 设置日志级别
		level, err := logrus.ParseLevel(c.Level)
		if err != nil {
			level = logrus.InfoLevel
			err = nil
		}
		Logger.SetLevel(level)

		// 设置 rotatelogs
		logWriter, _ := rotatelogs.New(
			// 分割后的文件名称
			fileName+".%Y%m%d.log",

			/*
				// 生成软链，指向最新日志文件
				rotatelogs.WithLinkName(fileName),
			*/

			// 设置最大保存时间(7天)
			rotatelogs.WithMaxAge(7*24*time.Hour),

			// 设置日志切割时间间隔(1天)
			rotatelogs.WithRotationTime(24*time.Hour),
		)

		writeMap := lfshook.WriterMap{
			logrus.InfoLevel:  logWriter,
			logrus.FatalLevel: logWriter,
			logrus.DebugLevel: logWriter,
			logrus.WarnLevel:  logWriter,
			logrus.ErrorLevel: logWriter,
			logrus.PanicLevel: logWriter,
		}

		lfHook := lfshook.NewHook(writeMap, &logrus.JSONFormatter{
			TimestampFormat: "2006-01-02 15:04:05",
		})

		// 新增 Hook
		Logger.AddHook(lfHook)
	})

	return
}

func getLogFields(c *gin.Context) logrus.Fields {
	startTime := time.UnixMicro(c.GetInt64(constant.RequestTime))
	if c.Request == nil {
		c.Request = new(http.Request)
	}
	return logrus.Fields{
		"logId":      c.GetInt64(constant.LogId),               // logId
		"statusCode": c.Writer.Status(),                        // 状态码
		"costTime":   time.Now().Sub(startTime).Milliseconds(), // 执行时间
		"clientIP":   c.ClientIP(),                             // 请求IP
		"reqMethod":  c.Request.Method,                         // 请求方式
		"reqUri":     c.Request.RequestURI,                     // 请求路由
		"referer":    c.Request.Referer(),                      // Referer
		"userAgent":  c.Request.UserAgent(),                    // UserAgent
	}
}

func Debug(c *gin.Context, msg ...interface{}) {
	Logger.WithFields(getLogFields(c)).Debug(msg)
}
func Debugf(c *gin.Context, format string, args ...interface{}) {
	if len(args) > 0 {
		Logger.WithFields(getLogFields(c)).Debugf(format, args...)
	} else {
		Logger.WithFields(getLogFields(c)).Debug(format)
	}
}

func Info(c *gin.Context, msg ...interface{}) {
	Logger.WithFields(getLogFields(c)).Info(msg)
}

func Infof(c *gin.Context, format string, args ...interface{}) {
	if len(args) > 0 {
		Logger.WithFields(getLogFields(c)).Infof(format, args...)
	} else {
		Logger.WithFields(getLogFields(c)).Infof(format)
	}
}

func Warningf(c *gin.Context, format string, args ...interface{}) {
	if len(args) > 0 {
		Logger.WithFields(getLogFields(c)).Warnf(format, args...)
	} else {
		Logger.WithFields(getLogFields(c)).Warnf(format)
	}
}

func Warning(c *gin.Context, msg ...interface{}) {
	Logger.WithFields(getLogFields(c)).Warning(msg)
}

func Error(c *gin.Context, err error) {
	Logger.WithFields(getLogFields(c)).WithError(err).Error()
}

func Errorf(c *gin.Context, err error, format string, args ...interface{}) {
	if len(args) > 0 {
		Logger.WithFields(getLogFields(c)).WithError(err).Errorf(format, args...)
	} else {
		Logger.WithFields(getLogFields(c)).WithError(err).Error(format)
	}
}

func Fatal(c *gin.Context, msg ...interface{}) {
	Logger.WithFields(getLogFields(c)).Fatal(msg)
}

func Fatalf(c *gin.Context, format string, args ...interface{}) {
	if len(args) > 0 {
		Logger.WithFields(getLogFields(c)).Fatalf(format, args...)
	} else {
		Logger.WithFields(getLogFields(c)).Fatalf(format)
	}
}

func Panic(c *gin.Context, msg ...interface{}) {
	Logger.WithFields(getLogFields(c)).Panic(msg)
}

func Panicf(c *gin.Context, format string, args ...interface{}) {
	if len(args) > 0 {
		Logger.WithFields(getLogFields(c)).Panicf(format, args...)
	} else {
		Logger.WithFields(getLogFields(c)).Panicf(format)
	}
}
